const { ccclass, property } = cc._decorator;
import ColorType from "./enum/color";
import BallTable from "./balltable";
import CPlayer from "./CPlayer";

import Boss from "./Boss";
import PlayerType from "./enum/player";
import BossType from "./enum/boss";

@ccclass
export default class Ground extends cc.Component {


    // LIFE-CYCLE CALLBACKS:

    @property(cc.SpriteFrame)
    endimg: cc.SpriteFrame

    @property([cc.SpriteFrame])
    num: cc.SpriteFrame[] = Array<cc.SpriteFrame>();

    @property([cc.SpriteFrame])
    color: cc.SpriteFrame[] = Array<cc.SpriteFrame>();

    @property(cc.Prefab)
    ball: cc.Prefab

    @property(BallTable)
    table: BallTable

    @property(CPlayer)
    player: CPlayer

    @property(Boss)
    boss: Boss

    @property(cc.AudioClip)
    groundBallAd: cc.AudioClip

    @property(cc.Node)
    maskNode: cc.Node
    @property(cc.Node)
    hand: cc.Node


    setUps: number = 0
    speed: number = 0.2
    playerSrcipt: { setAni: (arg0: PlayerType) => void; }
    bossSrcipt: { setAni: (arg0: BossType) => void; }
    bossBlood: cc.Node
    playerBlood: cc.Node
    playerTricks: cc.Node
    bossSkill: cc.Node

    AudioSource: cc.AudioSource

    isFirst: number

    //@ts-ignore
    balls: [{ num: number, color: ColorType }] = [
        { num: null, color: null },
        { num: null, color: null },
        { num: null, color: null },
        { num: null, color: null },
        { num: null, color: null },
        { num: null, color: null },
    ]

    ball_nums: number[] = [];
    colorType: ColorType = ColorType.Red;

    allBalls: [
        {
            num: number, color: ColorType
        }
    ]

    onLoad() {
        cc.systemEvent.on('gamestart', this.init, this)
        this.node.on(cc.Node.EventType.TOUCH_START, this.shutBall, this)
        this.playerSrcipt = this.player.getComponent("CPlayer")
        this.bossSrcipt = this.boss.getComponent("Boss")
        this.AudioSource = this.node.getComponent(cc.AudioSource)

        this.playerSrcipt.setAni(PlayerType.playerWait)
        cc.systemEvent.on("gameover", this.endGame, this)

        cc.find("Canvas/window").active = false
        cc.find("Canvas/mask").active = false
        cc.find("Canvas/mask").opacity = 255
        this.bossBlood = cc.find("Canvas/top/bossBlood")
        this.bossSkill = cc.find("Canvas/top/bossSkill")
        this.playerBlood = cc.find("Canvas/bottom/playerBlood")
        this.playerTricks = cc.find("Canvas/bottom/tricks/tricks")
    }

    start() {

    }

    endGame() {
        this.node.getComponent(cc.Button).normalSprite = this.endimg
        let x = Math.ceil(Math.random() * 1000) % 2 != 0 ? Math.ceil(Math.random() * 400) : -Math.ceil(Math.random() * 400)

        this.node.rotation = 40
        let target = this.boss.node.parent.convertToWorldSpaceAR(new cc.Vec2(this.boss.node.x, this.boss.node.y))
        let startTa = this.node.parent.convertToWorldSpaceAR(new cc.Vec2(this.node.x, this.node.y))
        const biz: cc.ActionInterval = cc.bezierTo(0.5, [new cc.Vec2(target.x - this.node.parent.parent.width / 2, target.y - this.node.parent.parent.height / 2),
        new cc.Vec2(x, 200),
        new cc.Vec2(startTa.x - this.node.parent.parent.width / 2, startTa.y - this.node.parent.parent.height / 2)])
        const func = cc.callFunc(function () {

            cc.find("Canvas/player").active = false
            cc.find("Canvas/window").active = true
            cc.find("Canvas/mask").active = true
            cc.find("Canvas/mask").opacity = 120
            cc.find("Canvas/boss").removeFromParent()

        })


        this.boss.node.scale = 0.05
        this.boss.node.runAction(cc.sequence([biz, func]))
    }


    shutBall() {
        this.playAudio(this.groundBallAd, false)
        this.setUps++

        if (this.isFirst != 1) {
            // this.bossSrcipt.setAni(BossType.skill)
            this.playerBlood.getComponent(cc.ProgressBar).progress = this.playerBlood.getComponent(cc.ProgressBar).progress - 0.01
            this.playerBlood.getChildByName("playerBlood").getComponent(cc.Label).string = Math.ceil(this.playerBlood.getComponent(cc.ProgressBar).progress * 100) + "/100"
            this.bossSkill.getComponent(cc.ProgressBar).progress = this.bossSkill.getComponent(cc.ProgressBar).progress + 0.05
            this.bossSkill.getChildByName("bossSkillNum").getComponent(cc.Label).string = Math.ceil(this.bossSkill.getComponent(cc.ProgressBar).progress / 0.05) + "/20"

        }
        this.isFirst++
        this.node.parent.getChildByName('ballBox').removeAllChildren()
        this.enabled = false
        let num = this.allBalls.length < 3 ? this.allBalls.length : 3;
        let getBalls = this.getBallByRandom(num)
        for (let index = 0; index < 3; index++) {
            const element = getBalls[index];
            if (element) {
                this.balls.push(element)
            } else {
                let obj = {
                    num: null,
                    color: null
                }
                this.balls.push(obj)
            }
        }

        for (let i = 0; i < 3; i++) {
            let newBall = cc.instantiate(this.ball);
            let ballScript = newBall.getComponent("Ball")
            if (this.balls[i + num].num != null && this.balls[i + num].color != null) {
                ballScript.setBallStyle(this.balls[i + num].color, this.balls[i + num].num)
            } else {
                ballScript.setBallStyle()
            }
            ballScript.setPositionBll(cc.v2(-37.5 + i * 20 + i * 37.5, 0))
            this.node.parent.getChildByName('ballBox').addChild(newBall)

        }

        for (let i = 0; i < 3; i++) {
            if (this.balls[i].num != null && this.balls[i].color != null) {
                this.allBalls.push(this.balls[i])
            }
        }
        this.balls.splice(0, 3)
        for (let index = 3; index < 6; index++) {
            const element = this.balls[index];
            let newBall = cc.instantiate(this.ball)
            let ballScript = newBall.getComponent("Ball")
            const num = element.num
            const color = element.color
            // ball.index = index + 3;
            if (num == null && color == null) {
                ballScript.setBallStyle()
            } else {
                ballScript.setBallStyle(color, num)
            }

            ballScript.setPositionBll(cc.v2(-37.5 - 50, -8))
            ballScript.setScaleBall(0.2)
            this.node.parent.getChildByName('ballBox').addChild(newBall)

            let t = cc.tween;
            t(newBall)
                // 同时执行两个 cc.tween
                .parallel(
                    t().to(this.speed, { scale: 1 }),
                    t().to(this.speed, { position: cc.v2(-37.5 + (index - 3) * 20 + (index - 3) * 37.5, -10) })
                )
                .call(() => {
                })
                .start()
        }

        for (let index = 0; index < this.node.parent.getChildByName('ballBox').children.length - 3; index++) {
            const element = this.node.parent.getChildByName('ballBox').children[index];
            cc.tween(element)
                .to(this.speed, { position: cc.v3(element.x, element.y + 10, -10) })
                .call(() => {
                })
                .start();
        }

        this.setSetUp()
        this.addBallOnclick()
    }

    addBallOnclick() {
        for (let index = 0; index < this.node.parent.getChildByName('ballBox').children.length; index++) {
            let aniColor = this.balls[index].color
            const item = this.node.parent.getChildByName('ballBox').children[index];
            if (index >= 3 && item.opacity == 255) {
                item.on(cc.Node.EventType.TOUCH_START, () => {
                    let result = this.addBall(index)
                    if (result) {
                        let ballsc = this.table.node.children[result.colIndex].getComponent("ballCol")
                        let resIndex = result.colIndex
                        cc.find("Canvas/mask").active = true
                        cc.find("Canvas/mask").opacity = 0
                        let x = Math.ceil(Math.random() * 1000) % 2 != 0 ? Math.ceil(Math.random() * 200) : -Math.ceil(Math.random() * 200)
                        let tempBall = cc.instantiate(this.ball)
                        let ballScript = tempBall.getComponent("Ball")
                        ballScript.setBallStyle(this.balls[index].color, this.balls[index].num)
                        let worldXy = this.node.parent.getChildByName('ballBox').convertToWorldSpaceAR(new cc.Vec2(item.x, item.y))
                        ballScript.setPositionBll(cc.v2(worldXy.x - this.node.parent.parent.width / 2, worldXy.y - this.node.parent.parent.height / 2))
                        this.node.parent.parent.addChild(tempBall)
                        this.clearBall(item, index)
                        const target = result.pos
                        const colIndex = result.colIndex


                        const biz: cc.ActionInterval = cc.bezierTo(0.5, [tempBall.getPosition(), new cc.Vec2(x, 100), cc.v2(target.x - this.node.parent.parent.width / 2, target.y - this.node.parent.parent.height / 2)])


                        let ballTableScript = this.table.getComponent("balltable")
                        const self = this

                        let tempcol = this.table.node.children[colIndex]
                        if (aniColor == ColorType.Red) {
                            this.playerSrcipt.setAni(PlayerType.attack_r)

                        } else {
                            this.playerSrcipt.setAni(PlayerType.attack_y)
                        }
                        this.bossSrcipt.setAni(BossType.bossInjured)
                        this.bossBlood.getComponent(cc.ProgressBar).progress = this.bossBlood.getComponent(cc.ProgressBar).progress - 0.01
                        this.bossBlood.getChildByName("bossBloodNum").getComponent(cc.Label).string = Math.ceil(this.bossBlood.getComponent(cc.ProgressBar).progress * 100) + "/100"



                        const func = cc.callFunc(async function () {
                            ballsc.DrawBalls(resIndex)
                            let tmScr = tempcol.getComponent("ballCol")
                            let moveToOther = ballTableScript.touchColToOther(tempcol)
                            let nowIndex = colIndex
                            if (moveToOther.isCan) {
                                tmScr.ball_nums = []
                                tmScr.DrawBalls(moveToOther.colIndex)
                                let resCol = this.table.node.children[moveToOther.RescolIndex]
                                tempcol = this.table.node.children[moveToOther.RescolIndex]
                                nowIndex = moveToOther.RescolIndex
                                while (moveToOther.isCan) {
                                    nowIndex = moveToOther.RescolIndex
                                    tempcol = this.table.node.children[moveToOther.RescolIndex]
                                    moveToOther = ballTableScript.touchColToOther(resCol)
                                    resCol = this.table.node.children[moveToOther.RescolIndex]
                                }
                            }

                            // 判断是否有其他珠子可以放进当前这一列
                            let moveToMe = ballTableScript.touchColToMe(tempcol)
                            let tempcolscript = tempcol.getComponent("ballCol")

                            if (moveToMe.isCan) {
                                let shouldReset = this.table.node.children[moveToMe.colIndex]
                                let shouldScipt = shouldReset.getComponent("ballCol")
                                shouldScipt.ball_nums = []
                                shouldScipt.DrawBalls(moveToMe.colIndex)
                                tempcolscript.ball_nums = moveToMe.ball_nums
                                tempcolscript.DrawBalls(nowIndex)
                            }

                            if (tempcolscript.ball_nums.length == 9) {


                                let boomCol = this.table.node.children[nowIndex]


                                for (let index = 0; index < boomCol.children.length; index++) {
                                    const element = boomCol.children[index];
                                    this.boomAni(element, index + 1)

                                }

                                setTimeout(() => {
                                    this.playerSrcipt.setAni(PlayerType.playerSkill)
                                    this.boss.setAni(BossType.bossDie)
                                    setTimeout(() => {
                                        this.node.active = false
                                        cc.find("Canvas/ground").active = true
                                        let anim = cc.find("Canvas/ground").getComponent(sp.Skeleton)
                                        anim.animation = "shou"
                                    }, 1000)
                                }, 550)



                                cc.find("Canvas/mask").active = true
                                cc.find("Canvas/mask").opacity = 0
                                this.bossBlood.getComponent(cc.ProgressBar).progress = 0
                                this.bossBlood.getChildByName("bossBloodNum").getComponent(cc.Label).string = "0/100"


                            }
                            // else {
                            //     if (aniColor == ColorType.Red) {
                            //         this.playerSrcipt.setAni(PlayerType.attack_r)

                            //     } else {
                            //         this.playerSrcipt.setAni(PlayerType.attack_y)
                            //     }
                            //     this.bossSrcipt.setAni(BossType.bossInjured)
                            //     this.bossBlood.getComponent(cc.ProgressBar).progress = this.bossBlood.getComponent(cc.ProgressBar).progress - 0.01
                            //     this.bossBlood.getChildByName("bossBloodNum").getComponent(cc.Label).string = Math.ceil(this.bossBlood.getComponent(cc.ProgressBar).progress * 100) + "/100"

                            // }
                            let trick = parseInt(this.playerTricks.getComponent(cc.Label).string) + 1
                            this.playerTricks.getComponent(cc.Label).string = trick.toString()
                            tempBall.destroy()
                            if (tempcolscript.ball_nums.length != 9) {
                                cc.find("Canvas/mask").active = false
                            }

                        }.bind(this));
                        this.setUps++

                        tempBall.runAction(cc.sequence([biz, func]));
                    }else{
                        this.shutBall()
                    }

                }, this)
            }
        }
    }


    boomAni(item, index) {

        //    const biz = cc.blink(1,1)
        setInterval(() => {

            let light = item.children[0]
            light.zIndex = 999
            light.opacity = 255
        }, 40 * index)
        setInterval(() => {

            item.removeFromParent()
        }, 50 * index)
        // item.runAction(cc.sequence([biz,func]))
    }

    clearBall(item: cc.Node, index: number) {
        this.node.parent.getChildByName('ballBox').removeChild(item)
        const temp = this.balls[index - 3]
        this.balls[index - 3] = { num: null, color: null }
        this.balls[index] = temp
        const _v1 = cc.moveTo(0.2, cc.v2(this.node.parent.getChildByName('ballBox').children[index - 3].x, this.node.parent.getChildByName('ballBox').children[index - 3].y - 20));
        this.node.parent.getChildByName('ballBox').children[index - 3].runAction(cc.sequence(_v1, cc.callFunc(() => {
            this.DrawBallBox()
        })))

        let count = 0

        for (let index = 0; index < this.balls.length; index++) {
            const element = this.balls[index];
            if (element.color == null && element.num == null) {
                count++
            }
        }
        if (count == 6 && this.isFirst != 1) {
            this.shutBall()
        }

    }
    DrawBallBox() {
        this.node.parent.getChildByName('ballBox').removeAllChildren()
        for (let index = 0; index < this.balls.length; index++) {
            const element = this.balls[index];
            let newBall = cc.instantiate(this.ball)
            let ballScript = newBall.getComponent("Ball")
            const num = element.num
            const color = element.color
            if (num == null && color == null) {
                ballScript.setBallStyle()
            } else {
                ballScript.setBallStyle(color, num)
            }



            this.node.parent.getChildByName('ballBox').addChild(newBall)
            newBall.x = 20 + index * 60
            newBall.y = 4
            if (index >= 3) {
                ballScript.setPositionBll(cc.v2(-37.5 + (index - 3) * 20 + (index - 3) * 37.5, -10))
            } else {
                ballScript.setPositionBll(cc.v2(-37.5 + index * 20 + index * 37.5, 10))
            }


        }
        this.setSetUp()
        this.addBallOnclick()
    }
    addBall(index?: number, nowColor?: ColorType, nowNum?: Number): { pos: cc.Vec2, colIndex: number, len: number, Xcoe: any } {
        let len: number
        let num: number | Number
        let color: ColorType
        if (index != null) {
            num = this.balls[index].num
            color = this.balls[index].color
        } else {
            num = nowNum
            color = nowColor
        }

        let Columns = this.table.node.children

        for (let o of Columns) {
            let ballColScript = o.getComponent("ballCol")
            const result = ballColScript.isCanAddBall(num, color, o)

            if (result.canAdd) {
                index = parseInt(o.name.substring(7))
                // ballColScript.DrawBalls(index)
                len = o.children.length
                let xCoe = this.switchXcoe(index)
                return { pos: result.pos, colIndex: index, len: len, Xcoe: xCoe }
            }
        }
        return null
    }


    update(dt: any) {
    }

    setFirstAni(light: cc.Node, thisNode: cc.Node, isGround?: boolean) {
        let speed = 0.3
        let endsc = 1.2
        let stdsc = 1
        if (isGround) {
            endsc = 0.556
            stdsc = 0.556
        }
        cc.tween(light)
            .repeatForever(
                cc.tween(light)
                    .to(speed, { opacity: 255 })
                    .to(speed, { opacity: 0 })
            )
            .start()

        cc.tween(thisNode)
            .repeatForever(
                cc.tween()
                    .to(speed, { scale: endsc })
                    .to(speed, { scale: stdsc })
            )
            .start()
    }

    setHandDownUP(pos) {
        let speed = 0.3
        cc.tween(this.hand)
            .repeatForever(
                cc.tween()
                    .to(speed, { position: cc.v3(pos.x, pos.y - 5, 0) })
                    .to(speed, { position: cc.v3(pos.x, pos.y + 5, 0) })
            )
            .start()
    }

    setSetUp() {
        if (this.setUps == 1) {
            let thisNode = this.node.parent.getChildByName('ballBox').children[3]
            let light = thisNode.getChildByName("light")

            this.setFirstAni(light, thisNode)

            this.node.parent.getChildByName('ballBox').children[4].opacity = 125
            this.node.parent.getChildByName('ballBox').children[5].opacity = 125

            this.hand.setPosition(0 - 17, 5)

            this.setHandDownUP(this.hand.getPosition(new cc.Vec3))
        } else if (this.setUps == 2) {
            let thisNode = this.node.parent.getChildByName('ballBox').children[4]
            let light = thisNode.getChildByName("light")
            this.setFirstAni(light, thisNode)
            this.node.parent.getChildByName('ballBox').children[5].opacity = 125
            cc.tween(this.hand).to(0.5, { position: cc.v3(60 - 17, 5) }).call(() => {
                this.hand.setPosition(60 - 17, 5)
                this.setHandDownUP(this.hand.getPosition(new cc.Vec3))

            }).start()
        } else if (this.setUps == 3) {
            let thisNode = this.node.parent.getChildByName('ballBox').children[5]
            let light = thisNode.getChildByName("light")
            this.setFirstAni(light, thisNode)


            cc.tween(this.hand).to(0.5, { position: cc.v3(120 - 17, 5) }).call(() => {
                this.hand.setPosition(120 - 17, 5)
                this.setHandDownUP(this.hand.getPosition(new cc.Vec3))
            }).start()
        } else if (this.setUps == 4) {
            let thisNode = this.node
            let light = thisNode.getChildByName("light")
            this.setFirstAni(light, thisNode, true)

            cc.tween(this.hand).to(0.5, { position: cc.v3(-118, -10) }).call(() => {
                this.hand.setPosition(-120, 5)
                this.setHandDownUP(this.hand.getPosition(new cc.Vec3))
            }).start()
            this.node.zIndex = 999
        }
        if (this.setUps == 5) {
            this.hand.destroy()
            this.maskNode.destroy()
            this.node.getChildByName("light").destroy()
        }
    }

    setAllBall() {
        this.allBalls = [{
            num: 1,
            color: ColorType.Red
        }]
        for (let index = 2; index <= 18; index++) {
            let obj = {
                num: index,
                color: ColorType.Red
            }
            if (index <= 9) {
                this.allBalls.push(obj)
            } else {
                obj.num = index - 9
                obj.color = ColorType.Yellow
                this.allBalls.push(obj)
            }
        }
    }



    getBallByRandom(num: number): any {
        const balls = []
        for (let i = 0; i < num; i++) {
            const index = Math.floor(Math.random() * this.allBalls.length)
            const element = this.allBalls[index];
            this.allBalls.splice(index, 1)
            balls.push(element)
        }
        return balls
    }

    init() {
        this.setAllBall()
        // this.initTable()
        // this.node.parent.getChildByName('ballBox').zIndex = 999
        this.shutBall()
        this.isFirst = 1
        cc.find("Canvas/player").zIndex = 999
        cc.find("Canvas/boss").zIndex = 999
        // let balls = this.getBallByRandom(3)
    }

    initTable() {

        for (let i = 0; i < 2; i++) {
            let getBalls = this.getBallByRandom(1)
            this.addBall(null, getBalls.color, getBalls.num)
        }

    }

    switchXcoe(colIndex: number): number {
        let xCoe: number = colIndex
        switch (xCoe) {
            case 0:
                xCoe = -3
                break;
            case 1:
                xCoe = -2
                break;
            case 2:
                xCoe = -1
                break;
            case 3:
                xCoe = 0
                break;
            case 4:
                xCoe = 1
                break;
            case 5:
                xCoe = 2
                break;
            case 6:
                xCoe = 3
                break;
            default:
                break;
        }
        return xCoe
    }


    playAudio(audioClip: cc.AudioClip, isLoop: boolean) {
        this.AudioSource.clip = audioClip
        if (isLoop) {
            this.AudioSource.loop = true
        }
        this.AudioSource.play()
    }
}
